static GSList *get_allocated_cells (GtkCellAreaBox *box,
GtkCellAreaBoxContext *context,
GtkWidget *widget,
- gint orientation_size);
+ gint width,
+ gint height);
struct _GtkCellAreaBoxPrivate
}
}
+/* Fall back on a completely unaligned dynamic allocation of cells
+ * when not allocated for the said orientation, alignment of cells
+ * is not done when each area gets a different size in the orientation
+ * of the box.
+ */
+static GSList *
+allocate_cells_manually (GtkCellAreaBox *box,
+ GtkWidget *widget,
+ gint width,
+ gint height)
+{
+ GtkCellAreaBoxPrivate *priv = box->priv;
+ GList *cells, *l;
+ GSList *allocated_cells = NULL;
+ GtkRequestedSize *sizes;
+ gint i;
+ gint nvisible = 0, nexpand = 0, group_expand;
+ gint avail_size, extra_size, extra_extra;
+ gint position = 0;
+
+ if (!priv->cells)
+ return NULL;
+
+ cells = list_consecutive_cells (box);
+
+ /* Count the visible and expand cells */
+ for (i = 0; i < priv->groups->len; i++)
+ {
+ CellGroup *group = &g_array_index (priv->groups, CellGroup, i);
+
+ nvisible += count_visible_cells (group, &group_expand);
+ nexpand += group_expand;
+ }
+
+ if (nvisible <= 0)
+ {
+ g_list_free (cells);
+ return NULL;
+ }
+
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+ avail_size = width;
+ else
+ avail_size = height;
+
+ /* Go ahead and collect the requests on the fly */
+ sizes = g_new0 (GtkRequestedSize, nvisible);
+ for (l = cells, i = 0; l; l = l->next)
+ {
+ CellInfo *info = l->data;
+
+ if (!gtk_cell_renderer_get_visible (info->renderer))
+ continue;
+
+ if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+ gtk_cell_renderer_get_preferred_width_for_height (info->renderer, widget, height,
+ &sizes[i].minimum_size,
+ &sizes[i].natural_size);
+ else
+ gtk_cell_renderer_get_preferred_height_for_width (info->renderer, widget, width,
+ &sizes[i].minimum_size,
+ &sizes[i].natural_size);
+
+ avail_size -= sizes[i].minimum_size;
+
+ sizes[i].data = info;
+
+ i++;
+ }
+
+ /* Naturally distribute the allocation */
+ avail_size -= (nvisible - 1) * priv->spacing;
+ avail_size = gtk_distribute_natural_allocation (avail_size, nvisible, sizes);
+
+ /* Calculate/distribute expand for cells */
+ if (nexpand > 0)
+ {
+ extra_size = avail_size / nexpand;
+ extra_extra = avail_size % nexpand;
+ }
+ else
+ extra_size = extra_extra = 0;
+
+ /* Create the allocated cells */
+ for (i = 0; i < nvisible; i++)
+ {
+ CellInfo *info = sizes[i].data;
+ AllocatedCell *cell;
+
+ if (info->expand)
+ {
+ sizes[i].minimum_size += extra_size;
+ if (extra_extra)
+ {
+ sizes[i].minimum_size++;
+ extra_extra--;
+ }
+ }
+
+ cell = allocated_cell_new (info->renderer, position, sizes[i].minimum_size);
+
+ allocated_cells = g_slist_prepend (allocated_cells, cell);
+
+ position += sizes[i].minimum_size;
+ position += priv->spacing;
+ }
+
+ g_free (sizes);
+ g_list_free (cells);
+
+ /* Note it might not be important to reverse the list here at all,
+ * we have the correct positions, no need to allocate from left to right */
+ return g_slist_reverse (allocated_cells);
+}
+
/* Returns an allocation for each cell in the orientation of the box,
* used in ->render()/->event() implementations to get a straight-forward
* list of allocated cells to operate on.
get_allocated_cells (GtkCellAreaBox *box,
GtkCellAreaBoxContext *context,
GtkWidget *widget,
- gint orientation_size)
+ gint width,
+ gint height)
{
GtkCellAreaBoxAllocation *group_allocs;
GtkCellArea *area = GTK_CELL_AREA (box);
GList *cell_list;
GSList *allocated_cells = NULL;
gint i, j, n_allocs;
- gboolean free_allocs = FALSE;
group_allocs = gtk_cell_area_box_context_get_orientation_allocs (context, &n_allocs);
if (!group_allocs)
- {
- group_allocs = gtk_cell_area_box_context_allocate (context, orientation_size, &n_allocs);
- free_allocs = TRUE;
- }
+ return allocate_cells_manually (box, widget, width, height);
for (i = 0; i < n_allocs; i++)
{
}
}
- if (free_allocs)
- g_free (group_allocs);
-
/* Note it might not be important to reverse the list here at all,
* we have the correct positions, no need to allocate from left to right */
return g_slist_reverse (allocated_cells);
/* Get a list of cells with allocation sizes decided regardless
* of alignments and pack order etc. */
allocated_cells = get_allocated_cells (box, box_context, widget,
- priv->orientation == GTK_ORIENTATION_HORIZONTAL ?
- cell_area->width : cell_area->height);
+ cell_area->width, cell_area->height);
for (l = allocated_cells; l; l = l->next)
{
/* Get a list of cells with allocation sizes decided regardless
* of alignments and pack order etc. */
allocated_cells = get_allocated_cells (box, box_context, widget,
- priv->orientation == GTK_ORIENTATION_HORIZONTAL ?
- cell_area->width : cell_area->height);
+ cell_area->width, cell_area->height);
for (l = allocated_cells; l; l = l->next)
{
/* Get a list of cells with allocation sizes decided regardless
* of alignments and pack order etc. */
allocated_cells = get_allocated_cells (box, box_context, widget,
- priv->orientation == GTK_ORIENTATION_HORIZONTAL ?
- cell_area->width : cell_area->height);
+ cell_area->width, cell_area->height);
for (l = allocated_cells; l; l = l->next)
{
/* GtkCellAreaContextClass */
static void gtk_cell_area_box_context_flush_preferred_width (GtkCellAreaContext *context);
-static void gtk_cell_area_box_context_flush_preferred_height_for_width (GtkCellAreaContext *context,
- gint width);
static void gtk_cell_area_box_context_flush_preferred_height (GtkCellAreaContext *context);
-static void gtk_cell_area_box_context_flush_preferred_width_for_height (GtkCellAreaContext *context,
- gint height);
static void gtk_cell_area_box_context_flush_allocation (GtkCellAreaContext *context);
static void gtk_cell_area_box_context_sum_preferred_width (GtkCellAreaContext *context);
-static void gtk_cell_area_box_context_sum_preferred_height_for_width (GtkCellAreaContext *context,
- gint width);
static void gtk_cell_area_box_context_sum_preferred_height (GtkCellAreaContext *context);
-static void gtk_cell_area_box_context_sum_preferred_width_for_height (GtkCellAreaContext *context,
- gint height);
-static void gtk_cell_area_box_context_allocate_width (GtkCellAreaContext *context,
- gint width);
-static void gtk_cell_area_box_context_allocate_height (GtkCellAreaContext *context,
+static void gtk_cell_area_box_context_allocate (GtkCellAreaContext *context,
+ gint width,
gint height);
-static void free_cache_array (GArray *array);
+static void free_cache_array (GArray *array);
+static GArray *group_array_new (GtkCellAreaBoxContext *context);
+static GArray *get_array (GtkCellAreaBoxContext *context,
+ GtkOrientation orientation,
+ gint for_size);
+static gboolean group_expands (GtkCellAreaBoxContext *context,
+ gint group_idx);
+static gint count_expand_groups (GtkCellAreaBoxContext *context);
+
/* CachedSize management */
typedef struct {
gint nat_size;
} CachedSize;
-typedef struct {
- gint min_size;
- gint nat_size;
- gboolean expand;
-} BaseSize;
-
struct _GtkCellAreaBoxContextPrivate
{
/* Table of per renderer CachedSizes */
GHashTable *widths;
GHashTable *heights;
+ /* Whether each group expands */
+ gboolean *expand;
+
/* Allocation info for this context if any */
gint alloc_width;
gint alloc_height;
g_array_free (array, TRUE);
}
+static GArray *
+group_array_new (GtkCellAreaBoxContext *context)
+{
+ GtkCellAreaBoxContextPrivate *priv = context->priv;
+ GArray *group_array;
+
+ group_array = g_array_new (FALSE, TRUE, sizeof (CachedSize));
+ g_array_set_size (group_array, priv->base_widths->len);
+
+ return group_array;
+}
+
+static GArray *
+get_array (GtkCellAreaBoxContext *context,
+ GtkOrientation orientation,
+ gint for_size)
+{
+ GtkCellAreaBoxContextPrivate *priv = context->priv;
+ GArray *array;
+
+ if (for_size < 0)
+ {
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ array = priv->base_widths;
+ else
+ array = priv->base_heights;
+ }
+ else
+ {
+ if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ {
+ array = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (for_size));
+
+ if (!array)
+ array = priv->base_widths;
+ }
+ else
+ {
+ array = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (for_size));
+
+ if (!array)
+ array = priv->base_heights;
+ }
+ }
+
+ return array;
+}
+
+static gboolean
+group_expands (GtkCellAreaBoxContext *context,
+ gint group_idx)
+{
+ GtkCellAreaBoxContextPrivate *priv = context->priv;
+
+ g_assert (group_idx >= 0 && group_idx < priv->base_widths->len);
+
+ return priv->expand[group_idx];
+}
+
+static gint
+count_expand_groups (GtkCellAreaBoxContext *context)
+{
+ GtkCellAreaBoxContextPrivate *priv = context->priv;
+ gint i, expand = 0;
+
+ for (i = 0; i < priv->base_widths->len; i++)
+ {
+ if (priv->expand[i])
+ expand++;
+ }
+
+ return expand;
+}
+
static void
gtk_cell_area_box_context_init (GtkCellAreaBoxContext *box_context)
{
GtkCellAreaBoxContextPrivate);
priv = box_context->priv;
- priv->base_widths = g_array_new (FALSE, TRUE, sizeof (BaseSize));
- priv->base_heights = g_array_new (FALSE, TRUE, sizeof (BaseSize));
+ priv->base_widths = g_array_new (FALSE, TRUE, sizeof (CachedSize));
+ priv->base_heights = g_array_new (FALSE, TRUE, sizeof (CachedSize));
priv->widths = g_hash_table_new_full (g_direct_hash, g_direct_equal,
NULL, (GDestroyNotify)free_cache_array);
/* GObjectClass */
object_class->finalize = gtk_cell_area_box_context_finalize;
- context_class->flush_preferred_width = gtk_cell_area_box_context_flush_preferred_width;
- context_class->flush_preferred_height_for_width = gtk_cell_area_box_context_flush_preferred_height_for_width;
- context_class->flush_preferred_height = gtk_cell_area_box_context_flush_preferred_height;
- context_class->flush_preferred_width_for_height = gtk_cell_area_box_context_flush_preferred_width_for_height;
- context_class->flush_allocation = gtk_cell_area_box_context_flush_allocation;
-
- context_class->sum_preferred_width = gtk_cell_area_box_context_sum_preferred_width;
- context_class->sum_preferred_height_for_width = gtk_cell_area_box_context_sum_preferred_height_for_width;
- context_class->sum_preferred_height = gtk_cell_area_box_context_sum_preferred_height;
- context_class->sum_preferred_width_for_height = gtk_cell_area_box_context_sum_preferred_width_for_height;
+ context_class->flush_preferred_width = gtk_cell_area_box_context_flush_preferred_width;
+ context_class->flush_preferred_height = gtk_cell_area_box_context_flush_preferred_height;
+ context_class->flush_allocation = gtk_cell_area_box_context_flush_allocation;
+ context_class->sum_preferred_width = gtk_cell_area_box_context_sum_preferred_width;
+ context_class->sum_preferred_height = gtk_cell_area_box_context_sum_preferred_height;
- context_class->allocate_width = gtk_cell_area_box_context_allocate_width;
- context_class->allocate_height = gtk_cell_area_box_context_allocate_height;
+ context_class->allocate = gtk_cell_area_box_context_allocate;
g_type_class_add_private (object_class, sizeof (GtkCellAreaBoxContextPrivate));
}
g_hash_table_destroy (priv->heights);
g_free (priv->orientation_allocs);
+ g_free (priv->expand);
G_OBJECT_CLASS (gtk_cell_area_box_context_parent_class)->finalize (object);
}
for (i = 0; i < priv->base_widths->len; i++)
{
- BaseSize *size = &g_array_index (priv->base_widths, BaseSize, i);
+ CachedSize *size = &g_array_index (priv->base_widths, CachedSize, i);
size->min_size = 0;
size->nat_size = 0;
}
- GTK_CELL_AREA_CONTEXT_CLASS
- (gtk_cell_area_box_context_parent_class)->flush_preferred_width (context);
-}
-
-static void
-gtk_cell_area_box_context_flush_preferred_height_for_width (GtkCellAreaContext *context,
- gint width)
-{
- GtkCellAreaBoxContext *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
- GtkCellAreaBoxContextPrivate *priv = box_context->priv;
-
- /* Flush all sizes for special -1 value */
- if (width < 0)
- g_hash_table_remove_all (priv->heights);
- else
- g_hash_table_remove (priv->heights, GINT_TO_POINTER (width));
+ /* Flush context widths as well */
+ g_hash_table_remove_all (priv->widths);
GTK_CELL_AREA_CONTEXT_CLASS
- (gtk_cell_area_box_context_parent_class)->flush_preferred_height_for_width (context, width);
+ (gtk_cell_area_box_context_parent_class)->flush_preferred_width (context);
}
static void
for (i = 0; i < priv->base_heights->len; i++)
{
- BaseSize *size = &g_array_index (priv->base_heights, BaseSize, i);
+ CachedSize *size = &g_array_index (priv->base_heights, CachedSize, i);
size->min_size = 0;
size->nat_size = 0;
}
- GTK_CELL_AREA_CONTEXT_CLASS
- (gtk_cell_area_box_context_parent_class)->flush_preferred_height (context);
-}
-
-static void
-gtk_cell_area_box_context_flush_preferred_width_for_height (GtkCellAreaContext *context,
- gint height)
-{
- GtkCellAreaBoxContext *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
- GtkCellAreaBoxContextPrivate *priv = box_context->priv;
-
- /* Flush all sizes for special -1 value */
- if (height < 0)
- g_hash_table_remove_all (priv->widths);
- else
- g_hash_table_remove (priv->widths, GINT_TO_POINTER (height));
+ /* Flush context heights as well */
+ g_hash_table_remove_all (priv->heights);
GTK_CELL_AREA_CONTEXT_CLASS
- (gtk_cell_area_box_context_parent_class)->flush_preferred_width_for_height (context, height);
+ (gtk_cell_area_box_context_parent_class)->flush_preferred_height (context);
}
static void
for (i = 0; i < priv->base_widths->len; i++)
{
- BaseSize *size = &g_array_index (priv->base_widths, BaseSize, i);
+ CachedSize *size = &g_array_index (priv->base_widths, CachedSize, i);
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
gtk_cell_area_context_push_preferred_width (context, min_size, nat_size);
}
-static void
-gtk_cell_area_box_context_sum_preferred_height_for_width (GtkCellAreaContext *context,
- gint width)
-{
- GtkCellAreaBoxContext *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
- GtkCellAreaBoxContextPrivate *priv = box_context->priv;
- GArray *group_array;
- GtkCellArea *area;
- GtkOrientation orientation;
- gint spacing, i;
- gint min_size = 0, nat_size = 0;
-
- group_array = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (width));
-
- if (group_array)
- {
- area = gtk_cell_area_context_get_area (context);
- spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
- orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
-
- for (i = 0; i < group_array->len; i++)
- {
- CachedSize *size = &g_array_index (group_array, CachedSize, i);
-
- if (orientation == GTK_ORIENTATION_VERTICAL)
- {
- /* Dont add spacing for 0 size groups, they can be 0 size because
- * they contain only invisible cells for this round of requests
- */
- if (min_size > 0 && size->nat_size > 0)
- {
- min_size += spacing;
- nat_size += spacing;
- }
-
- min_size += size->min_size;
- nat_size += size->nat_size;
- }
- else
- {
- min_size = MAX (min_size, size->min_size);
- nat_size = MAX (nat_size, size->nat_size);
- }
- }
-
- gtk_cell_area_context_push_preferred_height_for_width (context, width, min_size, nat_size);
- }
-}
-
static void
gtk_cell_area_box_context_sum_preferred_height (GtkCellAreaContext *context)
{
for (i = 0; i < priv->base_heights->len; i++)
{
- BaseSize *size = &g_array_index (priv->base_heights, BaseSize, i);
+ CachedSize *size = &g_array_index (priv->base_heights, CachedSize, i);
if (orientation == GTK_ORIENTATION_VERTICAL)
{
gtk_cell_area_context_push_preferred_height (context, min_size, nat_size);
}
-static void
-gtk_cell_area_box_context_sum_preferred_width_for_height (GtkCellAreaContext *context,
- gint height)
-{
- GtkCellAreaBoxContext *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
- GtkCellAreaBoxContextPrivate *priv = box_context->priv;
- GArray *group_array;
- GtkCellArea *area;
- GtkOrientation orientation;
- gint spacing, i;
- gint min_size = 0, nat_size = 0;
-
- group_array = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (height));
-
- if (group_array)
- {
- area = gtk_cell_area_context_get_area (context);
- spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
- orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
-
- for (i = 0; i < group_array->len; i++)
- {
- CachedSize *size = &g_array_index (group_array, CachedSize, i);
-
- if (orientation == GTK_ORIENTATION_HORIZONTAL)
- {
- /* Dont add spacing for 0 size groups, they can be 0 size because
- * they contain only invisible cells for this round of requests
- */
- if (min_size > 0 && size->nat_size > 0)
- {
- min_size += spacing;
- nat_size += spacing;
- }
-
- min_size += size->min_size;
- nat_size += size->nat_size;
- }
- else
- {
- min_size = MAX (min_size, size->min_size);
- nat_size = MAX (nat_size, size->nat_size);
- }
- }
-
- gtk_cell_area_context_push_preferred_width_for_height (context, height, min_size, nat_size);
- }
-}
-
static GtkRequestedSize *
gtk_cell_area_box_context_get_requests (GtkCellAreaBoxContext *box_context,
GtkOrientation orientation,
+ gint for_size,
gint *n_requests)
{
GtkCellAreaBoxContextPrivate *priv;
GtkRequestedSize *requests;
- GArray *base_array;
- BaseSize *size;
+ GArray *array;
+ CachedSize *size;
gint visible_groups = 0;
gint i, j;
g_return_val_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context), NULL);
- priv = box_context->priv;
+ priv = box_context->priv;
+ array = get_array (box_context, orientation, for_size);
- if (orientation == GTK_ORIENTATION_HORIZONTAL)
- base_array = priv->base_widths;
- else
- base_array = priv->base_heights;
-
- for (i = 0; i < base_array->len; i++)
+ for (i = 0; i < array->len; i++)
{
- size = &g_array_index (base_array, BaseSize, i);
+ size = &g_array_index (array, CachedSize, i);
if (size->nat_size > 0)
visible_groups++;
requests = g_new (GtkRequestedSize, visible_groups);
- for (j = 0, i = 0; i < base_array->len; i++)
+ for (j = 0, i = 0; i < array->len; i++)
{
- size = &g_array_index (base_array, BaseSize, i);
+ size = &g_array_index (array, CachedSize, i);
if (size->nat_size > 0)
{
GtkOrientation orientation,
gint spacing,
gint size,
+ gint for_size,
gint *n_allocs)
{
- GtkCellAreaBoxContextPrivate *priv = context->priv;
- GtkRequestedSize *orientation_sizes;
GtkCellAreaBoxAllocation *allocs;
+ GtkRequestedSize *sizes;
+ GArray *array;
gint n_expand_groups = 0;
gint i, n_groups, position;
gint extra_size, extra_extra;
gint avail_size = size;
- orientation_sizes =
- gtk_cell_area_box_context_get_requests (context, orientation, &n_groups);
-
- /* Count groups that expand */
- for (i = 0; i < n_groups; i++)
- {
- BaseSize *size;
- gint group_idx = GPOINTER_TO_INT (orientation_sizes[i].data);
-
- if (orientation == GTK_ORIENTATION_HORIZONTAL)
- size = &g_array_index (priv->base_widths, BaseSize, group_idx);
- else
- size = &g_array_index (priv->base_heights, BaseSize, group_idx);
-
- if (size->expand)
- n_expand_groups++;
- }
+ sizes = gtk_cell_area_box_context_get_requests (context, orientation, for_size, &n_groups);
+ array = get_array (context, orientation, for_size);
+ n_expand_groups = count_expand_groups (context);
/* First start by naturally allocating space among groups */
avail_size -= (n_groups - 1) * spacing;
for (i = 0; i < n_groups; i++)
- avail_size -= orientation_sizes[i].minimum_size;
+ avail_size -= sizes[i].minimum_size;
- avail_size = gtk_distribute_natural_allocation (avail_size, n_groups, orientation_sizes);
+ avail_size = gtk_distribute_natural_allocation (avail_size, n_groups, sizes);
/* Calculate/distribute expand for groups */
if (n_expand_groups > 0)
for (position = 0, i = 0; i < n_groups; i++)
{
- BaseSize *base_size = &g_array_index (priv->base_widths, BaseSize, i);
-
- allocs[i].group_idx = GPOINTER_TO_INT (orientation_sizes[i].data);
+ allocs[i].group_idx = GPOINTER_TO_INT (sizes[i].data);
allocs[i].position = position;
- allocs[i].size = orientation_sizes[i].minimum_size;
+ allocs[i].size = sizes[i].minimum_size;
- if (base_size->expand)
+ if (group_expands (context, allocs[i].group_idx))
{
allocs[i].size += extra_size;
if (extra_extra)
if (n_allocs)
*n_allocs = n_groups;
- g_free (orientation_sizes);
+ g_free (sizes);
return allocs;
}
static void
-gtk_cell_area_box_context_allocate_width (GtkCellAreaContext *context,
- gint width)
+gtk_cell_area_box_context_allocate (GtkCellAreaContext *context,
+ gint width,
+ gint height)
{
GtkCellAreaBoxContext *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
GtkCellAreaBoxContextPrivate *priv = box_context->priv;
GtkCellArea *area;
GtkOrientation orientation;
+ gint spacing;
area = gtk_cell_area_context_get_area (context);
orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
+ spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
- if (orientation == GTK_ORIENTATION_HORIZONTAL)
+ if (orientation == GTK_ORIENTATION_HORIZONTAL && width > 0)
{
- gint spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
-
g_free (priv->orientation_allocs);
- priv->orientation_allocs = allocate_for_orientation (box_context, orientation, spacing, width,
+ priv->orientation_allocs = allocate_for_orientation (box_context, orientation,
+ spacing, width, height,
&priv->n_orientation_allocs);
}
-
- GTK_CELL_AREA_CONTEXT_CLASS (gtk_cell_area_box_context_parent_class)->allocate_width (context, width);
-}
-
-static void
-gtk_cell_area_box_context_allocate_height (GtkCellAreaContext *context,
- gint height)
-{
- GtkCellAreaBoxContext *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
- GtkCellAreaBoxContextPrivate *priv = box_context->priv;
- GtkCellArea *area;
- GtkOrientation orientation;
-
- area = gtk_cell_area_context_get_area (context);
- orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
-
- if (orientation == GTK_ORIENTATION_VERTICAL)
+ else if (orientation == GTK_ORIENTATION_VERTICAL && height > 0)
{
- gint spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
-
g_free (priv->orientation_allocs);
- priv->orientation_allocs = allocate_for_orientation (box_context, orientation, spacing, height,
+ priv->orientation_allocs = allocate_for_orientation (box_context, orientation,
+ spacing, height, width,
&priv->n_orientation_allocs);
}
- GTK_CELL_AREA_CONTEXT_CLASS (gtk_cell_area_box_context_parent_class)->allocate_height (context, height);
+ GTK_CELL_AREA_CONTEXT_CLASS (gtk_cell_area_box_context_parent_class)->allocate (context, width, height);
}
gboolean *expand_groups)
{
GtkCellAreaBoxContextPrivate *priv;
- gint i;
g_return_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context));
g_return_if_fail (n_groups == 0 || expand_groups != NULL);
/* When the group dimensions change, all info must be flushed
- * Note this already clears the min/nat values on the BaseSizes
+ * Note this already clears the min/nat values on the CachedSizes
*/
gtk_cell_area_context_flush (GTK_CELL_AREA_CONTEXT (box_context));
g_array_set_size (priv->base_widths, n_groups);
g_array_set_size (priv->base_heights, n_groups);
- /* Now set the expand info */
- for (i = 0; i < n_groups; i++)
- {
- BaseSize *base_width = &g_array_index (priv->base_widths, BaseSize, i);
- BaseSize *base_height = &g_array_index (priv->base_heights, BaseSize, i);
-
- base_width->expand = expand_groups[i];
- base_height->expand = expand_groups[i];
- }
+ g_free (priv->expand);
+ priv->expand = g_memdup (expand_groups, n_groups * sizeof (gboolean));
}
void
gint natural_width)
{
GtkCellAreaBoxContextPrivate *priv;
- BaseSize *size;
+ CachedSize *size;
g_return_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context));
priv = box_context->priv;
g_return_if_fail (group_idx < priv->base_widths->len);
- size = &g_array_index (priv->base_widths, BaseSize, group_idx);
+ size = &g_array_index (priv->base_widths, CachedSize, group_idx);
size->min_size = MAX (size->min_size, minimum_width);
size->nat_size = MAX (size->nat_size, natural_width);
}
group_array = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (for_width));
if (!group_array)
{
- group_array = g_array_new (FALSE, TRUE, sizeof (CachedSize));
- g_array_set_size (group_array, priv->base_heights->len);
-
+ group_array = group_array_new (box_context);
g_hash_table_insert (priv->heights, GINT_TO_POINTER (for_width), group_array);
}
gint natural_height)
{
GtkCellAreaBoxContextPrivate *priv;
- BaseSize *size;
+ CachedSize *size;
g_return_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context));
priv = box_context->priv;
g_return_if_fail (group_idx < priv->base_heights->len);
- size = &g_array_index (priv->base_heights, BaseSize, group_idx);
+ size = &g_array_index (priv->base_heights, CachedSize, group_idx);
size->min_size = MAX (size->min_size, minimum_height);
size->nat_size = MAX (size->nat_size, natural_height);
}
gint natural_width)
{
GtkCellAreaBoxContextPrivate *priv;
- GArray *group_array;
- CachedSize *size;
+ GArray *group_array;
+ CachedSize *size;
g_return_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context));
group_array = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (for_height));
if (!group_array)
{
- group_array = g_array_new (FALSE, TRUE, sizeof (CachedSize));
- g_array_set_size (group_array, priv->base_heights->len);
-
+ group_array = group_array_new (box_context);
g_hash_table_insert (priv->widths, GINT_TO_POINTER (for_height), group_array);
}
gint *natural_width)
{
GtkCellAreaBoxContextPrivate *priv;
- BaseSize *size;
+ CachedSize *size;
g_return_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context));
priv = box_context->priv;
g_return_if_fail (group_idx < priv->base_widths->len);
- size = &g_array_index (priv->base_widths, BaseSize, group_idx);
+ size = &g_array_index (priv->base_widths, CachedSize, group_idx);
if (minimum_width)
*minimum_width = size->min_size;
gint *natural_height)
{
GtkCellAreaBoxContextPrivate *priv;
- BaseSize *size;
+ CachedSize *size;
g_return_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context));
priv = box_context->priv;
g_return_if_fail (group_idx < priv->base_heights->len);
- size = &g_array_index (priv->base_heights, BaseSize, group_idx);
+ size = &g_array_index (priv->base_heights, CachedSize, group_idx);
if (minimum_height)
*minimum_height = size->min_size;
gtk_cell_area_box_context_get_widths (GtkCellAreaBoxContext *box_context,
gint *n_widths)
{
- return gtk_cell_area_box_context_get_requests (box_context, GTK_ORIENTATION_HORIZONTAL, n_widths);
+ return gtk_cell_area_box_context_get_requests (box_context, GTK_ORIENTATION_HORIZONTAL, -1, n_widths);
}
GtkRequestedSize *
gtk_cell_area_box_context_get_heights (GtkCellAreaBoxContext *box_context,
gint *n_heights)
{
- return gtk_cell_area_box_context_get_requests (box_context, GTK_ORIENTATION_VERTICAL, n_heights);
+ return gtk_cell_area_box_context_get_requests (box_context, GTK_ORIENTATION_VERTICAL, -1, n_heights);
}
GtkCellAreaBoxAllocation *
*n_allocs = priv->n_orientation_allocs;
return priv->orientation_allocs;
-
-}
-
-GtkCellAreaBoxAllocation *
-gtk_cell_area_box_context_allocate (GtkCellAreaBoxContext *context,
- gint orientation_size,
- gint *n_allocs)
-{
- GtkCellArea *area;
- GtkOrientation orientation;
- gint spacing;
-
- area = gtk_cell_area_context_get_area (GTK_CELL_AREA_CONTEXT (context));
- orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
- spacing = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
-
- return allocate_for_orientation (context, orientation, spacing, orientation_size, n_allocs);
}
#include "gtkprivate.h"
/* GObjectClass */
-static void gtk_cell_area_context_finalize (GObject *object);
static void gtk_cell_area_context_dispose (GObject *object);
static void gtk_cell_area_context_get_property (GObject *object,
guint prop_id,
/* GtkCellAreaContextClass */
static void gtk_cell_area_context_real_flush_preferred_width (GtkCellAreaContext *context);
-static void gtk_cell_area_context_real_flush_preferred_height_for_width (GtkCellAreaContext *context,
- gint width);
static void gtk_cell_area_context_real_flush_preferred_height (GtkCellAreaContext *context);
-static void gtk_cell_area_context_real_flush_preferred_width_for_height (GtkCellAreaContext *context,
- gint height);
static void gtk_cell_area_context_real_flush_allocation (GtkCellAreaContext *context);
-static void gtk_cell_area_context_real_allocate_width (GtkCellAreaContext *context,
- gint width);
-static void gtk_cell_area_context_real_allocate_height (GtkCellAreaContext *context,
+static void gtk_cell_area_context_real_allocate (GtkCellAreaContext *context,
+ gint width,
gint height);
-/* CachedSize management */
-typedef struct {
- gint min_size;
- gint nat_size;
-} CachedSize;
-
-static CachedSize *cached_size_new (gint min_size, gint nat_size);
-static void cached_size_free (CachedSize *size);
-
struct _GtkCellAreaContextPrivate
{
GtkCellArea *cell_area;
gint nat_height;
gint alloc_width;
gint alloc_height;
-
- GHashTable *widths;
- GHashTable *heights;
};
enum {
PROP_NAT_HEIGHT
};
-enum {
- SIGNAL_WIDTH_CHANGED,
- SIGNAL_HEIGHT_CHANGED,
- LAST_SIGNAL
-};
-
-static guint cell_area_context_signals[LAST_SIGNAL] = { 0 };
-
G_DEFINE_TYPE (GtkCellAreaContext, gtk_cell_area_context, G_TYPE_OBJECT);
static void
priv->nat_width = -1;
priv->min_height = -1;
priv->nat_height = -1;
- priv->widths = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, (GDestroyNotify)cached_size_free);
- priv->heights = g_hash_table_new_full (g_direct_hash, g_direct_equal,
- NULL, (GDestroyNotify)cached_size_free);
}
static void
GObjectClass *object_class = G_OBJECT_CLASS (class);
/* GObjectClass */
- object_class->finalize = gtk_cell_area_context_finalize;
object_class->dispose = gtk_cell_area_context_dispose;
object_class->get_property = gtk_cell_area_context_get_property;
object_class->set_property = gtk_cell_area_context_set_property;
/* GtkCellAreaContextClass */
- class->flush_preferred_width = gtk_cell_area_context_real_flush_preferred_width;
- class->flush_preferred_height_for_width = gtk_cell_area_context_real_flush_preferred_height_for_width;
- class->flush_preferred_height = gtk_cell_area_context_real_flush_preferred_height;
- class->flush_preferred_width_for_height = gtk_cell_area_context_real_flush_preferred_width_for_height;
- class->flush_allocation = gtk_cell_area_context_real_flush_allocation;
-
- class->sum_preferred_width = NULL;
- class->sum_preferred_height_for_width = NULL;
- class->sum_preferred_height = NULL;
- class->sum_preferred_width_for_height = NULL;
-
- class->allocate_width = gtk_cell_area_context_real_allocate_width;
- class->allocate_height = gtk_cell_area_context_real_allocate_height;
-
- cell_area_context_signals[SIGNAL_HEIGHT_CHANGED] =
- g_signal_new (I_("height-changed"),
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- 0, /* Class offset (just a notification, no class handler) */
- NULL, NULL,
- _gtk_marshal_VOID__INT_INT_INT,
- G_TYPE_NONE, 3,
- G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
-
- cell_area_context_signals[SIGNAL_WIDTH_CHANGED] =
- g_signal_new (I_("width-changed"),
- G_TYPE_FROM_CLASS (object_class),
- G_SIGNAL_RUN_LAST,
- 0, /* Class offset (just a notification, no class handler) */
- NULL, NULL,
- _gtk_marshal_VOID__INT_INT_INT,
- G_TYPE_NONE, 3,
- G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
+ class->flush_preferred_width = gtk_cell_area_context_real_flush_preferred_width;
+ class->flush_preferred_height = gtk_cell_area_context_real_flush_preferred_height;
+ class->flush_allocation = gtk_cell_area_context_real_flush_allocation;
+ class->sum_preferred_width = NULL;
+ class->sum_preferred_height = NULL;
+ class->allocate = gtk_cell_area_context_real_allocate;
g_object_class_install_property (object_class,
PROP_CELL_AREA,
g_type_class_add_private (object_class, sizeof (GtkCellAreaContextPrivate));
}
-
-
-/*************************************************************
- * Cached Sizes *
- *************************************************************/
-static CachedSize *
-cached_size_new (gint min_size,
- gint nat_size)
-{
- CachedSize *size = g_slice_new (CachedSize);
-
- size->min_size = min_size;
- size->nat_size = nat_size;
-
- return size;
-}
-
-static void
-cached_size_free (CachedSize *size)
-{
- g_slice_free (CachedSize, size);
-}
-
/*************************************************************
* GObjectClass *
*************************************************************/
-static void
-gtk_cell_area_context_finalize (GObject *object)
-{
- GtkCellAreaContext *context = GTK_CELL_AREA_CONTEXT (object);
- GtkCellAreaContextPrivate *priv = context->priv;
-
- g_hash_table_destroy (priv->widths);
- g_hash_table_destroy (priv->heights);
-
- G_OBJECT_CLASS (gtk_cell_area_context_parent_class)->finalize (object);
-}
-
static void
gtk_cell_area_context_dispose (GObject *object)
{
g_object_thaw_notify (G_OBJECT (context));
}
-static void
-notify_invalid_height (gpointer width_ptr,
- CachedSize *size,
- GtkCellAreaContext *context)
-{
- gint width = GPOINTER_TO_INT (width_ptr);
-
- /* Notify size invalidated */
- g_signal_emit (context, cell_area_context_signals[SIGNAL_HEIGHT_CHANGED],
- 0, width, -1, -1);
-}
-
-static void
-gtk_cell_area_context_real_flush_preferred_height_for_width (GtkCellAreaContext *context,
- gint width)
-{
- GtkCellAreaContextPrivate *priv = context->priv;
-
- /* Flush all sizes for special -1 value */
- if (width < 0)
- {
- g_hash_table_foreach (priv->heights, (GHFunc)notify_invalid_height, context);
- g_hash_table_remove_all (priv->heights);
- }
- else
- {
- g_hash_table_remove (priv->heights, GINT_TO_POINTER (width));
-
- /* Notify size invalidated */
- g_signal_emit (context, cell_area_context_signals[SIGNAL_HEIGHT_CHANGED],
- 0, width, -1, -1);
- }
-}
-
static void
gtk_cell_area_context_real_flush_preferred_height (GtkCellAreaContext *context)
{
g_object_thaw_notify (G_OBJECT (context));
}
-static void
-notify_invalid_width (gpointer height_ptr,
- CachedSize *size,
- GtkCellAreaContext *context)
-{
- gint height = GPOINTER_TO_INT (height_ptr);
-
- /* Notify size invalidated */
- g_signal_emit (context, cell_area_context_signals[SIGNAL_WIDTH_CHANGED],
- 0, height, -1, -1);
-}
-
-static void
-gtk_cell_area_context_real_flush_preferred_width_for_height (GtkCellAreaContext *context,
- gint height)
-{
- GtkCellAreaContextPrivate *priv = context->priv;
-
- /* Flush all sizes for special -1 value */
- if (height < 0)
- {
- g_hash_table_foreach (priv->widths, (GHFunc)notify_invalid_width, context);
- g_hash_table_remove_all (priv->widths);
- }
- else
- {
- g_hash_table_remove (priv->widths, GINT_TO_POINTER (height));
-
- /* Notify size invalidated */
- g_signal_emit (context, cell_area_context_signals[SIGNAL_WIDTH_CHANGED],
- 0, height, -1, -1);
- }
-}
-
static void
gtk_cell_area_context_real_flush_allocation (GtkCellAreaContext *context)
{
}
static void
-gtk_cell_area_context_real_allocate_width (GtkCellAreaContext *context,
- gint width)
-{
- GtkCellAreaContextPrivate *priv = context->priv;
-
- priv->alloc_width = width;
-}
-
-static void
-gtk_cell_area_context_real_allocate_height (GtkCellAreaContext *context,
- gint height)
+gtk_cell_area_context_real_allocate (GtkCellAreaContext *context,
+ gint width,
+ gint height)
{
GtkCellAreaContextPrivate *priv = context->priv;
+ priv->alloc_width = width;
priv->alloc_height = height;
}
-
/*************************************************************
* API *
*************************************************************/
g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
gtk_cell_area_context_flush_preferred_width (context);
- gtk_cell_area_context_flush_preferred_height_for_width (context, -1);
gtk_cell_area_context_flush_preferred_height (context);
- gtk_cell_area_context_flush_preferred_width_for_height (context, -1);
gtk_cell_area_context_flush_allocation (context);
}
GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->flush_preferred_width (context);
}
-void
-gtk_cell_area_context_flush_preferred_height_for_width (GtkCellAreaContext *context,
- gint for_width)
-{
- g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
-
- GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->flush_preferred_height_for_width (context, for_width);
-}
-
void
gtk_cell_area_context_flush_preferred_height (GtkCellAreaContext *context)
{
GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->flush_preferred_height (context);
}
-void
-gtk_cell_area_context_flush_preferred_width_for_height (GtkCellAreaContext *context,
- gint for_height)
-{
- g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
-
- GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->flush_preferred_width_for_height (context, for_height);
-}
-
void
gtk_cell_area_context_flush_allocation (GtkCellAreaContext *context)
{
class->sum_preferred_width (context);
}
-void
-gtk_cell_area_context_sum_preferred_height_for_width (GtkCellAreaContext *context,
- gint for_width)
-{
- GtkCellAreaContextClass *class;
-
- g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
-
- class = GTK_CELL_AREA_CONTEXT_GET_CLASS (context);
-
- if (class->sum_preferred_height_for_width)
- class->sum_preferred_height_for_width (context, for_width);
-}
-
void
gtk_cell_area_context_sum_preferred_height (GtkCellAreaContext *context)
{
}
void
-gtk_cell_area_context_sum_preferred_width_for_height (GtkCellAreaContext *context,
- gint for_height)
+gtk_cell_area_context_allocate (GtkCellAreaContext *context,
+ gint width,
+ gint height)
{
GtkCellAreaContextClass *class;
class = GTK_CELL_AREA_CONTEXT_GET_CLASS (context);
- if (class->sum_preferred_width_for_height)
- class->sum_preferred_width_for_height (context, for_height);
-}
-
-void
-gtk_cell_area_context_allocate_width (GtkCellAreaContext *context,
- gint width)
-{
- GtkCellAreaContextClass *class;
-
- g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
-
- class = GTK_CELL_AREA_CONTEXT_GET_CLASS (context);
-
- class->allocate_width (context, width);
-}
-
-void
-gtk_cell_area_context_allocate_height (GtkCellAreaContext *context,
- gint height)
-{
- GtkCellAreaContextClass *class;
-
- g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
-
- class = GTK_CELL_AREA_CONTEXT_GET_CLASS (context);
-
- class->allocate_height (context, height);
+ class->allocate (context, width, height);
}
void
*natural_width = priv->nat_width;
}
-void
-gtk_cell_area_context_get_preferred_height_for_width (GtkCellAreaContext *context,
- gint for_width,
- gint *minimum_height,
- gint *natural_height)
-{
- GtkCellAreaContextPrivate *priv;
- CachedSize *size;
-
- g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
-
- priv = context->priv;
-
- size = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (for_width));
-
- if (size)
- {
- if (minimum_height)
- *minimum_height = size->min_size;
-
- if (natural_height)
- *natural_height = size->nat_size;
- }
- else
- {
- if (minimum_height)
- *minimum_height = -1;
-
- if (natural_height)
- *natural_height = -1;
- }
-}
-
void
gtk_cell_area_context_get_preferred_height (GtkCellAreaContext *context,
gint *minimum_height,
*natural_height = priv->nat_height;
}
-void
-gtk_cell_area_context_get_preferred_width_for_height (GtkCellAreaContext *context,
- gint for_height,
- gint *minimum_width,
- gint *natural_width)
-{
- GtkCellAreaContextPrivate *priv;
- CachedSize *size;
-
- g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
-
- priv = context->priv;
-
- size = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (for_height));
-
- if (size)
- {
- if (minimum_width)
- *minimum_width = size->min_size;
-
- if (natural_width)
- *natural_width = size->nat_size;
- }
- else
- {
- if (minimum_width)
- *minimum_width = -1;
-
- if (natural_width)
- *natural_width = -1;
- }
-}
-
void
gtk_cell_area_context_get_allocation (GtkCellAreaContext *context,
gint *width,
g_object_thaw_notify (G_OBJECT (context));
}
-void
-gtk_cell_area_context_push_preferred_height_for_width (GtkCellAreaContext *context,
- gint for_width,
- gint minimum_height,
- gint natural_height)
-{
- GtkCellAreaContextPrivate *priv;
- CachedSize *size;
- gboolean changed = FALSE;
-
- g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
-
- priv = context->priv;
-
- size = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (for_width));
-
- if (!size)
- {
- size = cached_size_new (minimum_height, natural_height);
-
- g_hash_table_insert (priv->heights, GINT_TO_POINTER (for_width), size);
-
- changed = TRUE;
- }
- else
- {
- if (minimum_height > size->min_size)
- {
- size->min_size = minimum_height;
- changed = TRUE;
- }
-
- if (natural_height > size->nat_size)
- {
- size->nat_size = natural_height;
- changed = TRUE;
- }
- }
-
- if (changed)
- g_signal_emit (context, cell_area_context_signals[SIGNAL_HEIGHT_CHANGED], 0,
- for_width, size->min_size, size->nat_size);
-}
-
void
gtk_cell_area_context_push_preferred_height (GtkCellAreaContext *context,
gint minimum_height,
g_object_thaw_notify (G_OBJECT (context));
}
-
-void
-gtk_cell_area_context_push_preferred_width_for_height (GtkCellAreaContext *context,
- gint for_height,
- gint minimum_width,
- gint natural_width)
-{
- GtkCellAreaContextPrivate *priv;
- CachedSize *size;
- gboolean changed = FALSE;
-
- g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
-
- priv = context->priv;
-
- size = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (for_height));
-
- if (!size)
- {
- size = cached_size_new (minimum_width, natural_width);
-
- g_hash_table_insert (priv->widths, GINT_TO_POINTER (for_height), size);
-
- changed = TRUE;
- }
- else
- {
- if (minimum_width > size->min_size)
- {
- size->min_size = minimum_width;
- changed = TRUE;
- }
-
- if (natural_width > size->nat_size)
- {
- size->nat_size = natural_width;
- changed = TRUE;
- }
- }
-
- if (changed)
- g_signal_emit (context, cell_area_context_signals[SIGNAL_WIDTH_CHANGED], 0,
- for_height, size->min_size, size->nat_size);
-}